#ifndef _KC_RECEIVERBASE_H__KC_
#define _KC_RECEIVERBASE_H__KC_

#include <string>
#include <list>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "../data/SMTPDefaults.h"
#include "../data/Command.h"
#include "../data/Reply.h"
#include "../../comm/CommRequestHandler.h"
#include "../../comm/CommCommon.h"
#include "../../comm/Connection.h"
#include "../../logs/Logger.h"
#include "../../mime/data/RawMessage.h"

#define now microsec_clock::local_time()

using namespace boost::posix_time;
using namespace boost::gregorian;

namespace kc_sf
{
	// pomocnicze typy i klasy
	enum ReceiverState
	{
		InitState,
		ConnectedState,
		HelloState,
		MailState,
		RcptState,
        DataState,
        BdatState
	};

	/** Klasa bazowa do komunikacji SMTP z klientami.
	 * Wymaga uwierzytelnienia przed rozpoczeciem pobierania wiadomosci.
	 * */
	class Receiver : public CommRequestHandler
	{
		public:

			Receiver() {}
			explicit Receiver( const Connection &connection );
			Receiver( CommCommon *comm, const Connection &connection );
			virtual ~Receiver();

			virtual CommRequestHandler *getInstance( const Connection &connection ) const;

			virtual void operator()();

			virtual CommResult processHelo( const Command & cmd );
			virtual CommResult processEhlo( const Command & cmd );
			virtual CommResult processBaseHelo( const Command &cmd, Reply &reply );
			virtual CommResult processNoop();
			virtual CommResult processQuit();
			virtual CommResult processRset();
			virtual CommResult processUnimplemented( const Command & cmd );
			virtual CommResult processUndefined( const Command & cmd );

			virtual CommResult processAuthPlain();
			virtual CommResult processAuthLogin();
			virtual CommResult processStartTLS();
			virtual CommResult processMailFrom( const Command & cmd );
			virtual CommResult processRcpt( const Command & cmd );
			virtual CommResult processData();
			virtual CommResult processBdat( const Command & cmd );

			virtual CommResult recvCommand(Command & cmd, int timeout_s = DEF_RECEIVER_TIMEOUT_S );
			virtual CommResult recvLine( std::string &to, int timeout_s = DEF_RECEIVER_TIMEOUT_S );
			virtual CommResult recvData( std::string &to, int timeout_s = DEF_RECEIVER_TIMEOUT_S );
			virtual CommResult recvData( std::string &to, const std::string &until, int timeout_s = DEF_RECEIVER_TIMEOUT_S );
			virtual CommResult sendReply(const Reply & reply, int timeout_s = DEF_RECEIVER_TIMEOUT_S);

		protected:

			ReceiverState r_state;
			CommCommon *r_comm;
			std::string r_cl_name;
			RawMessage r_msg;
			//std::list <Command > r_pipelined;
			Logger r_logger;

			virtual bool isAllowedInState(int cmd_type);
	};
}

#endif // _KC_RECEIVERBASE_H__KC_
